From 730765de9163934d9993b25a87f076f1b36ed271 Mon Sep 17 00:00:00 2001 From: Ryan Lortie Date: Fri, 6 Jan 2012 15:37:05 -0500 Subject: [PATCH] GtkWindow: new API to store state in GSettings https://bugzilla.gnome.org/show_bug.cgi?id=667438 --- docs/reference/gtk/gtk3-sections.txt | 1 + gtk/Makefile.am | 6 +- gtk/gtk.symbols | 1 + gtk/gtkwindow.c | 128 +++++++++++++++++++++++++++ gtk/gtkwindow.h | 4 + gtk/org.gtk.WindowState.gschema.xml | 10 +++ 6 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 gtk/org.gtk.WindowState.gschema.xml diff --git a/docs/reference/gtk/gtk3-sections.txt b/docs/reference/gtk/gtk3-sections.txt index 02e7ce5615..0e0499a647 100644 --- a/docs/reference/gtk/gtk3-sections.txt +++ b/docs/reference/gtk/gtk3-sections.txt @@ -5322,6 +5322,7 @@ gtk_window_fullscreen gtk_window_unfullscreen gtk_window_set_keep_above gtk_window_set_keep_below +gtk_window_setup_persistent_state gtk_window_begin_resize_drag gtk_window_begin_move_drag gtk_window_set_decorated diff --git a/gtk/Makefile.am b/gtk/Makefile.am index ab46644c24..bcac2cf235 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -1508,10 +1508,12 @@ EXTRA_DIST += \ gtktypebuiltins.h.template \ gtkprivatetypebuiltins.c.template \ gtkprivatetypebuiltins.h.template \ - org.gtk.Settings.FileChooser.gschema.xml + org.gtk.Settings.FileChooser.gschema.xml \ + org.gtk.WindowState.gschema.xml gsettings_SCHEMAS = \ - org.gtk.Settings.FileChooser.gschema.xml + org.gtk.Settings.FileChooser.gschema.xml \ + org.gtk.WindowState.gschema.xml @GSETTINGS_RULES@ diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols index 2006c170c7..5129f86240 100644 --- a/gtk/gtk.symbols +++ b/gtk/gtk.symbols @@ -3876,6 +3876,7 @@ gtk_window_set_transient_for gtk_window_set_type_hint gtk_window_set_urgency_hint gtk_window_set_wmclass +gtk_window_setup_persistent_state gtk_window_stick gtk_window_type_get_type gtk_window_unfullscreen diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index 62e75ee45a..a4b9dd3898 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -132,6 +132,9 @@ struct _GtkWindowPrivate guint16 configure_request_count; + GSettings *state_settings; + guint state_save_id; + /* The following flags are initially TRUE (before a window is mapped). * They cause us to compute a configure request that involves * default-only parameters. Once mapped, we set them to FALSE. @@ -4590,6 +4593,40 @@ gtk_window_reshow_with_initial_size (GtkWindow *window) gtk_widget_show (widget); } +static gboolean +gtk_window_persistent_state_flush (gpointer user_data) +{ + GtkWindow *window = user_data; + GtkWidget *widget = user_data; + gboolean was_maximized; + gboolean is_maximized; + + was_maximized = g_settings_get_boolean (window->priv->state_settings, "is-maximized"); + is_maximized = gdk_window_get_state (gtk_widget_get_window (widget)) & GDK_WINDOW_STATE_MAXIMIZED; + + if (is_maximized != was_maximized) + g_settings_set_boolean (window->priv->state_settings, "is-maximized", is_maximized); + + if (!is_maximized) + { + gint old_width, old_height; + GtkAllocation size; + + G_STATIC_ASSERT (sizeof (size.width) == sizeof (int)); + + g_settings_get (window->priv->state_settings, "size", "(ii)", &old_width, &old_height); + gtk_widget_get_allocation (widget, &size); + + if (size.width != old_width || size.height != old_height) + g_settings_set (window->priv->state_settings, "size", "(ii)", size.width, size.height); + } + + g_source_remove (window->priv->state_save_id); + window->priv->state_save_id = 0; + + return G_SOURCE_REMOVE; +} + static void gtk_window_destroy (GtkWidget *widget) { @@ -5231,6 +5268,9 @@ gtk_window_unrealize (GtkWidget *widget) GtkWindowPrivate *priv = window->priv; GtkWindowGeometryInfo *info; + if (window->priv->state_save_id) + gtk_window_persistent_state_flush (window); + /* On unrealize, we reset the size of the window such * that we will re-apply the default sizing stuff * next time we show the window. @@ -5426,6 +5466,14 @@ gtk_window_size_allocate (GtkWidget *widget, GtkWidget *child; guint border_width; + if (window->priv->state_settings) + { + if (window->priv->state_save_id) + g_source_remove (window->priv->state_save_id); + + window->priv->state_save_id = g_timeout_add (1000, gtk_window_persistent_state_flush, window); + } + gtk_widget_set_allocation (widget, allocation); if (gtk_widget_get_realized (widget)) @@ -9721,3 +9769,83 @@ ensure_state_flag_window_unfocused (GtkWidget *widget) gtk_widget_queue_draw (widget); } + +/** + * gtk_window_setup_persistent_state: + * @window: a #GtkWindow + * @settings: a #GSettings object + * @child_name: the name of a child on @settings with schema + * 'org.gtk.WindowState' + * + * Sets up persistent window state using #GSettings. + * + * The size of the window and its maximized state is saved. + * + * At the time of the call, the values are read out of GSettings and + * applied to the window as the default size and maximized state. This + * must be done before the window is shown. + * + * When the size or maximized state of the window is changed, the + * updated values are stored back into GSettings (with an unspecified + * delay to prevent trashing). + * + * @child_name must be the name of a child of @settings (ie: + * g_settings_get_child() must succeed). The resulting #GSettings + * object must have the schema 'org.gtk.WindowState', which is installed + * by Gtk. + * + * Your application's schema should look something like this: + * + * |[ + * ... keys ... + * + * + * + * ]]>]| + * + * Then you should call this function like this: + * + * |[ + * GSettings *settings; + * + * settings = g_settings_new ("org.example.awesome"); + * gtk_window_setup_persistent_state (window, settings, "main-window-state"); + * ]| + * + * You may only call this function once per window. + * + * Since: 3.4 + **/ +void +gtk_window_setup_persistent_state (GtkWindow *window, + GSettings *settings, + const gchar *child_name) +{ + gint width, height; + GSList *node; + + g_return_if_fail (GTK_IS_WINDOW (window)); + g_return_if_fail (G_IS_SETTINGS (settings)); + g_return_if_fail (child_name != NULL); + g_return_if_fail (window->priv->state_settings == NULL); + + /* Force other windows to flush their state first. We may be sharing + * the same settings as they are and we want to see them up to date... + */ + for (node = toplevel_list; node; node = node->next) + { + GtkWindow *w = node->data; + + if (w->priv->state_save_id) + gtk_window_persistent_state_flush (w); + g_assert (w->priv->state_save_id == 0); + } + + window->priv->state_settings = g_settings_get_child (settings, child_name); + window->priv->maximize_initially = g_settings_get_boolean (window->priv->state_settings, "is-maximized"); + + g_settings_get (window->priv->state_settings, "size", "(ii)", &width, &height); + if (width > 0 && height > 0) + gtk_window_set_default_size (window, width, height); +} diff --git a/gtk/gtkwindow.h b/gtk/gtkwindow.h index 17203070e2..01b3eb3d5a 100644 --- a/gtk/gtkwindow.h +++ b/gtk/gtkwindow.h @@ -338,6 +338,10 @@ gboolean gtk_window_get_has_resize_grip (GtkWindow *window); gboolean gtk_window_resize_grip_is_visible (GtkWindow *window); gboolean gtk_window_get_resize_grip_area (GtkWindow *window, GdkRectangle *rect); +void gtk_window_setup_persistent_state (GtkWindow *window, + GSettings *settings, + const gchar *child_name); + G_END_DECLS diff --git a/gtk/org.gtk.WindowState.gschema.xml b/gtk/org.gtk.WindowState.gschema.xml new file mode 100644 index 0000000000..966edf6284 --- /dev/null +++ b/gtk/org.gtk.WindowState.gschema.xml @@ -0,0 +1,10 @@ + + + + (-1, -1) + + + false + + + -- 2.30.2